<template>
  <div id="select-image" >
    <div class="image-list clearfix" :class="{ multiple }">
      <!-- 文件列表 -->
      <draggable
        v-if="selectedItems.length"
        v-model="selectedItems"
        @start="drag=true"
        @end="drag=false"
        @update="onUpdate"
        >
        <transition-group class="draggable-item" type="transition" :name="'flip-list'">
          <div 
            v-for="(item, index) in selectedItems"
            :key="item.file_id"
            class="file-item"
            :style="{ width: `${ width }px`, height: `${ width }px` }"
            >
              <!-- 显示默认图片 -->
              <!-- 预览图, 其中属性target="_blank的意思是在新页面打开该链接,形成父子界面的关系 -->
              <a :href="item.external_url" target="_blank">
                <el-image
                  class="img-cover"
                  :style="`width: ${ width }px; height: ${ width }px`"
                  :src="item.preview_url"
                  fit="scale-down"/>
                <!-- <div class="img-cover" :style="{ backgroundImage: `url('${ item.preview_url }')` }"></div> -->
              </a>
              <i
                class="el-icon-error"
                @click="handleDeleteFileItem(index)"></i>
          </div>
        </transition-group>
      </draggable>
      <!-- 图片选择器 -->
      <!-- 如果单选, selectedItems无内容时 显示 -->
      <!-- 如果多选, selectedItems数量小于 maxNum 显示 -->
      <div 
        v-show="(!multiple && selectedItems.length <= 0) || (multiple && selectedItems.length < maxNum)"
        class="selector"
        :style="{width: `${width}px`, height: `${width}px`}"
        title="点击选择图片"
        @click="handleSelectImage"
        >
          <i class="el-icon-plus" :style="{ fontSize: `${ width * 0.4 }px` }"></i>
      </div>
      <!-- 文件选择器 -->
      <FilesModal 
        ref="FilesModal"
        :multiple="multiple"
        :maxNum="maxNum"
        :selectedNum="selectedItems.length"
        :appendToBody="appendToBody ? true : false"
        @handleSubmit="handleSelectImageSubmit"
      />
    </div>
  </div>
</template>

<script>
import draggable from 'vuedraggable'
import cloneDeep from 'lodash.clonedeep'
import { FilesModal } from '@/components/Modal'

// 图片选择器组件
export default {
  name: 'SelectImage',
  components: { FilesModal, draggable },
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    // 多选模式, 如果false为单选
    multiple: { type: Boolean, default: false },
    // 最大选择的数量限制, multiple模式下有效
    maxNum: { type: Number, default: 100 },
    // maxNum: PropTypes.integer.def(100),
    // 默认选中的文件
    defaultList: { type: Array, default: () => [] },
    // 元素的尺寸(宽)
    width: { type: Number, default: 80 },
    // 是否为内置遮罩层
    appendToBody: { type: Boolean, default: false },
  },
  data () {
    return {
      // 选择的图片列表(file-list)
      selectedItems: [],
      // 禁止传参 (防止selectedItems为空时defaultList重新赋值)
      allowProps: true,
    }
  },
  watch: {
    // 设置默认数据
    defaultList: {
      // 首次加载的时候执行函数
      immediate: true,
      handler(val) {
        // this.selectedItems = []
        const { selectedItems, allowProps } = this
        if (val.length && !selectedItems.length && allowProps) {
          this.selectedItems = cloneDeep(val)
          this.onChange()
        }
      },
    },
  },
  methods: {
    // 拖动排序后的回调事件
    onUpdate () {
      this.onChange()
    },
    // 打开文件选择器
    handleSelectImage () {
      this.$refs.FilesModal.show()
    },
    // 文件库中modal确认回调
    handleSelectImageSubmit(result) {
      // result == selectedItem(选中的文件数据数组)
      if(result.length > 0) {
        // 记录选中的图片列表
        const { multiple, selectedItems } = this;
        // 将选中的文件数据数据赋值给这边的selectedItems内保存
        this.selectedItems = multiple ? selectedItems.concat(result) : result
        this.onChange()
      }
    },
    // 删除文件
    handleDeleteFileItem(index) {
      this.selectedItems.splice(index, 1)
      if(this.selectedItems.length === 0) {
        this.allowProps = false
      }
      this.onChange()
    },
    // 触发change事件
    onChange() {
      const { multiple, selectedItems } = this;
      // 没有选择图片
      if(selectedItems.length <= 0) {
        // 双向绑定,change就相当于input的change事件,直接修改父组件内的双向绑定的值
        return this.$emit('change', multiple ? [] : 0)
      }
      // 生成fileId
      const fileId = multiple ? selectedItems.map(item => item.file_id) : selectedItems[0].file_id
      // 触发change事件
      return this.$emit('change', fileId, selectedItems)
    },
    // 将选中的图片清空
    clearSelectItem() {
      this.selectedItems = []
      this.allowProps = true
    }
  }
}
</script>

<style lang="less" scoped>
/deep/.flip-list-move {
  transition: transform 0.3s !important;
}
/deep/.no-move {
  transition: transform 0s;
}

.image-list {
  // 多选模式下margin
  &.multiple {
    .file-item,
    .selector {
      margin-right: 10px;
      margin-bottom: 10px;
    }
  }
}

// 文件元素
.file-item {
  position: relative;
  float: left;
  width: 80px;
  height: 80px;
  position: relative;
  padding: 2px;
  border: 1px solid #ddd;
  background: #fff;
  .img-cover {
    display: block;
    width: 100%;
    height: 100%;
    background: no-repeat center center / 100%;
  }
  &:hover {
    .el-icon-error {
      display: block;
    }
  }
  .el-icon-error {
    display: none;
    position: absolute;
    top: -8px;
    right: -8px;
    cursor: pointer;
    font-size: 16px;
    color: #c5c5c5;
    &:hover {
      color: #7d7d7d;
    }
  }
  &:hover {
    border: 1px solid #a7c3de;
  }
}

// 选择器
.selector {
  width: 80px;
  height: 80px;
  float: left;
  border: 1px dashed #e2e2e2;
  text-align: center;
  color: #dad9d9;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  &:hover {
    border: 1px dashed #40a9ff;
    color: #40a9ff;
  }
  .el-icon-plus {
    font-size: 32px;
  }
}
</style>
